# Copyright (c) Open Enclave SDK contributors.
# Licensed under the MIT License.

set(OPENSSL_DIR ${PROJECT_SOURCE_DIR}/3rdparty/openssl/openssl)
set(OPENSSL_3_DIR ${PROJECT_SOURCE_DIR}/3rdparty/openssl/openssl_3)

add_subdirectory(host)
if (BUILD_ENCLAVES)
  add_subdirectory(enc)
endif ()

macro (copy_test_data OLD_FILE NEW_FILE)
  if (UNIX)
    add_custom_command(OUTPUT ${NEW_FILE} COMMAND ${CMAKE_COMMAND} -E copy
                                                  ${OLD_FILE} ${NEW_FILE})
  else ()
    # On Windows, invoking the dos2unix utility from git to replace
    # CRLF by LF in the test file.
    add_custom_command(OUTPUT ${NEW_FILE} COMMAND ${OE_DOS2UNIX} -n ${OLD_FILE}
                                                  ${NEW_FILE})
  endif ()

  # Add the copied files to the list so that the custom target
  # openssl_test_data can take dependency on.
  list(APPEND test_data_list ${NEW_FILE})
endmacro (copy_test_data)

# Copy the following test data from the OpenSSL repository so that we can enforce
# LF on Windows.

# The following files are required by the evp_test, which uses the file parsing
# APIs provided by the testutil library (i.e., see stanza.c for detail). The
# parsing API (test_readstanza) has a special logic to handle a blank line and
# assumes it ends with only `\n` (LF). Therefore, the API fails when the blank
# line ends with `\r\n` (CRLF).
set(OPENSSL_SHARED_EVP_TEST_LIST evpencod evppkey_ecc)
foreach (subtestname ${OPENSSL_SHARED_EVP_TEST_LIST})
  # We'll use the version from OpenSSL 1.0; it should be the same.
  copy_test_data(
    ${OPENSSL_DIR}/test/recipes/30-test_evp_data/${subtestname}.txt
    ${CMAKE_CURRENT_BINARY_DIR}/30-test_evp_data/${subtestname}.txt)
endforeach ()

set(OPENSSL_1_EVP_TEST_LIST
    evpcase
    evpccmcavs
    evpciph
    evpdigest
    evpencod
    evpkdf
    evpmac
    evppbe
    evppkey
    evppkey_ecc)
foreach (subtestname ${OPENSSL_1_EVP_TEST_LIST})
  copy_test_data(
    ${OPENSSL_DIR}/test/recipes/30-test_evp_data/${subtestname}.txt
    ${CMAKE_CURRENT_BINARY_DIR}/30-test_evp_data/openssl/${subtestname}.txt)
endforeach ()

set(OPENSSL_3_EVP_TEST_LIST
    evpciph_aes_ccm_cavs
    evpciph_camellia_cts
    evpciph_seed
    evpkdf_tls11_prf
    evpmac_siphash
    evppbe_scrypt
    evppkey_kdf_hkdf
    evpciph_aes_common
    evpciph_cast5
    evpciph_sm4
    evpkdf_tls12_prf
    evpmd_blake
    evppkey_brainpool
    evppkey_kdf_scrypt
    evpciph_aes_cts
    evpciph_chacha
    evpencod
    evpkdf_tls13_kdf
    evpmd_md
    evppkey_dh
    evppkey_kdf_tls1_prf
    evpciph_aes_ocb
    evpciph_des
    evpkdf_hkdf
    evpkdf_x942
    evpmd_mdc2
    evppkey_dsa
    evppkey_mismatch
    evpciph_aes_siv
    evpciph_des3_common
    evpkdf_krb5
    evpkdf_x942_des
    evpmd_ripemd
    evppkey_ecc
    evppkey_rsa
    evpciph_aes_stitched
    evpciph_idea
    evpkdf_pbkdf1
    evpkdf_x963
    evpmd_sha
    evppkey_ecdh
    evppkey_rsa_common
    evpciph_aes_wrap
    evpciph_rc2
    evpkdf_pbkdf2
    evpmac_blake
    evpmd_sm3
    evppkey_ecdsa
    # evppkey_sm2     # NOTE: requires sm2
    evpciph_aria
    evpciph_rc4
    evpkdf_scrypt
    evpmac_cmac_des
    evpmd_whirlpool
    evppkey_ecx
    evprand
    evpciph_bf
    evpciph_rc4_stitched
    evpkdf_ss
    evpmac_common
    evppbe_pbkdf2
    evppkey_ffdhe
    evpciph_camellia
    evpciph_rc5
    evpkdf_ssh
    evpmac_poly1305
    evppbe_pkcs12
    evppkey_kas)
foreach (subtestname ${OPENSSL_3_EVP_TEST_LIST})
  copy_test_data(
    ${OPENSSL_3_DIR}/test/recipes/30-test_evp_data/${subtestname}.txt
    ${CMAKE_CURRENT_BINARY_DIR}/30-test_evp_data/openssl_3/${subtestname}.txt)
endforeach ()

# The following file is required by params_conversion_test, which also uses the
# file parsing APIs provided by the testutil library and fails on  `\r\n` (CRLF).
copy_test_data(
  ${OPENSSL_3_DIR}/test/recipes/04-test_params_conversion_data/native_types.txt
  ${CMAKE_CURRENT_BINARY_DIR}/04-test_params_conversion_data/native_types.txt)

# The following files are required by the ct_test. The test compares the in-memory
# string generated by the X509V3_EXT_print and SCT_LIST_print APIs against the
# content of the *.sct files. Given these APIs use `\n` (LF) as an end-of-line (EOL)
# by default, the comparison fails if the content of the file ends with `\r\n` (CRLF).
# Note that the EOL of the *.pem files does not affect the test results. However,
# because the test uses a same path to retrieve *.sct and *.pem files, we copy the *.pem
# files as well.
copy_test_data(${OPENSSL_DIR}/test/certs/bad.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/bad.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/ca-cert.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/ca-cert.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/ee-cert.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/ee-cert.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/embeddedSCTs1.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/embeddedSCTs1.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/embeddedSCTs1.sct
               ${CMAKE_CURRENT_BINARY_DIR}/certs/embeddedSCTs1.sct)
copy_test_data(${OPENSSL_DIR}/test/certs/embeddedSCTs1_issuer.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/embeddedSCTs1_issuer.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/embeddedSCTs3.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/embeddedSCTs3.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/embeddedSCTs3.sct
               ${CMAKE_CURRENT_BINARY_DIR}/certs/embeddedSCTs3.sct)
copy_test_data(${OPENSSL_DIR}/test/certs/embeddedSCTs3_issuer.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/embeddedSCTs3_issuer.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/leaf.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/leaf.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/rootCA.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/rootCA.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/roots.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/roots.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/sroot-cert.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/sroot-cert.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/subinterCA.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/subinterCA.pem)
copy_test_data(${OPENSSL_DIR}/test/certs/untrusted.pem
               ${CMAKE_CURRENT_BINARY_DIR}/certs/untrusted.pem)
copy_test_data(${OPENSSL_DIR}/test/ct/tls1.sct
               ${CMAKE_CURRENT_BINARY_DIR}/ct/tls1.sct)

# Add a custom target that ensures the test files are copied at build time.
add_custom_target(openssl_test_data ALL DEPENDS ${test_data_list})

file(STRINGS "tests.unsupported.symcrypt" UNSUPPORTED_SYMCRYPT_TESTS)
file(STRINGS "tests_3.unsupported.symcrypt" UNSUPPORTED_SYMCRYPT_TESTS_3)

# Add buildtests.
file(STRINGS "tests.supported.buildtest" buildtests)
foreach (testcase ${buildtests})
  get_testcase_name(${testcase} name "../../3rdparty/openssl/openssl/test/")
  add_enclave_test(tests/openssl/${name} openssl_host openssl-${name}_enc
                   ${name})
  if ((NOT "${name}" IN_LIST UNSUPPORTED_SYMCRYPT_TESTS)
      AND (ENABLE_SYMCRYPT_OPENSSL_TESTS))
    add_enclave_test(tests/openssl/${name}_symcrypt openssl_host
                     openssl-${name}_symcrypt_enc ${name})
  endif ()
endforeach (testcase)

# Add buildtests for OpenSSL_3
file(STRINGS "tests_3.supported.buildtest" buildtests_3)
foreach (testcase ${buildtests_3})
  get_testcase_name(${testcase} name "../../3rdparty/openssl/openssl_3/test/")
  add_enclave_test(tests/openssl/3-${name} openssl_host openssl-3-${name}_enc
                   ${name})
  if ((NOT "${name}" IN_LIST UNSUPPORTED_SYMCRYPT_TESTS_3)
      AND (ENABLE_SYMCRYPT_OPENSSL_TESTS))
    add_enclave_test(tests/openssl/3-${name}_symcrypt openssl_host
                     openssl-3-${name}_symcrypt_enc ${name})
  endif ()
endforeach (testcase)

# Helper for adding tests with arguments.
macro (add_openssl_test OPENSSL3 TEST_NAME NAME)
  if (OPENSSL3)
    add_enclave_test(tests/openssl/3-${TEST_NAME} openssl_host
                     openssl-3-${NAME}_enc ${TEST_NAME} ${ARGN})

    if ((NOT "${TEST_NAME}" IN_LIST UNSUPPORTED_SYMCRYPT_TESTS_3)
        AND (ENABLE_SYMCRYPT_OPENSSL_TESTS))
      add_enclave_test(tests/openssl/3-${TEST_NAME}_symcrypt openssl_host
                       openssl-3-${NAME}_symcrypt_enc ${TEST_NAME} ${ARGN})
    endif ()
  else ()
    add_enclave_test(tests/openssl/${TEST_NAME} openssl_host
                     openssl-${NAME}_enc ${TEST_NAME} ${ARGN})

    if ((NOT "${TEST_NAME}" IN_LIST UNSUPPORTED_SYMCRYPT_TESTS)
        AND (ENABLE_SYMCRYPT_OPENSSL_TESTS))
      add_enclave_test(tests/openssl/${TEST_NAME}_symcrypt openssl_host
                       openssl-${NAME}_symcrypt_enc ${TEST_NAME} ${ARGN})
    endif ()
  endif ()
endmacro (add_openssl_test)

# Helper for adding tests with properties.
macro (add_openssl_tests_properties OPENSSL3 TEST_NAME)
  if (OPENSSL3)
    set_enclave_tests_properties(tests/openssl/3-${TEST_NAME} ${ARGN})
    if ((NOT "${TEST_NAME}" IN_LIST UNSUPPORTED_SYMCRYPT_TESTS_3)
        AND (ENABLE_SYMCRYPT_OPENSSL_TESTS))
      set_enclave_tests_properties(tests/openssl/3-${TEST_NAME}_symcrypt
                                   ${ARGN})
    endif ()
  else ()
    set_enclave_tests_properties(tests/openssl/${TEST_NAME} ${ARGN})
    if ((NOT "${TEST_NAME}" IN_LIST UNSUPPORTED_SYMCRYPT_TESTS)
        AND (ENABLE_SYMCRYPT_OPENSSL_TESTS))
      set_enclave_tests_properties(tests/openssl/${TEST_NAME}_symcrypt ${ARGN})
    endif ()
  endif ()
endmacro (add_openssl_tests_properties)

# Helper to handle correct input arguments for tests.
function (add_openssl_test_supported NAME OPENSSL3)
  # The paths to the arguments used by the tests.
  set(TEST_DATA_DIR ${CMAKE_CURRENT_BINARY_DIR})
  if (OPENSSL3)
    set(OPENSSL_APPS_DIR ${OPENSSL_3_DIR}/apps)
    set(OPENSSL_TEST_DIR ${OPENSSL_3_DIR}/test)
    set(OPENSSL_RECIPE_DIR ${OPENSSL_3_DIR}/test/recipes)
    set(OPENSSL_CTLOG_FILE ${OPENSSL_TEST_DIR}/ct/log_list.cnf)
  else ()
    set(OPENSSL_APPS_DIR ${OPENSSL_DIR}/apps)
    set(OPENSSL_TEST_DIR ${OPENSSL_DIR}/test)
    set(OPENSSL_RECIPE_DIR ${OPENSSL_DIR}/test/recipes)
    set(OPENSSL_CTLOG_FILE ${OPENSSL_TEST_DIR}/ct/log_list.conf)
  endif ()

  if (WIN32)
    # Convert the "C:/" to "C/" so that the path can be used by hostfs on Windows.
    string(REPLACE ":" "" OPENSSL_APPS_DIR "${OPENSSL_APPS_DIR}")
    string(REPLACE ":" "" OPENSSL_TEST_DIR "${OPENSSL_TEST_DIR}")
    string(REPLACE ":" "" OPENSSL_RECIPE_DIR "${OPENSSL_RECIPE_DIR}")
    string(REPLACE ":" "" OPENSSL_CTLOG_FILE "${OPENSSL_CTLOG_FILE}")
    string(REPLACE ":" "" TEST_DATA_DIR "${TEST_DATA_DIR}")
  endif ()

  # Some specific tests require command line arguments.
  # Some binaries need to be run multiple times with different arguments.
  # Arguments are based on files at openssl/test/recipes/.
  if ("${name}" STREQUAL algorithmid_test)
    add_openssl_test(
      OPENSSL3 "${name}-1" "${name}" "-x509"
      ${OPENSSL_TEST_DIR}/certs/ee-cert.pem
      ${OPENSSL_TEST_DIR}/certs/ca-cert.pem)
    add_openssl_test(
      OPENSSL3 "${name}-2" "${name}" "-x509"
      ${OPENSSL_TEST_DIR}/certs/ee-cert2.pem
      ${OPENSSL_TEST_DIR}/certs/ca-cert2.pem)
    return()
  endif ()

  if ("${name}" STREQUAL asynciotest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_APPS_DIR}/server.pem
      ${OPENSSL_APPS_DIR}/server.pem)
    return()
  endif ()

  if ("${name}" STREQUAL bio_readbuffer_test)
    add_openssl_test(OPENSSL3 "${name}-pem" "${name}"
                     ${OPENSSL_APPS_DIR}/server.pem)
    add_openssl_test(OPENSSL3 "${name}-der" "${name}"
                     ${OPENSSL_RECIPE_DIR}/65-test_cmp_msg_data/pkcs10.der)
    return()
  endif ()

  if ("${name}" STREQUAL clienthellotest)
    add_openssl_test(OPENSSL3 "${name}" "${name}"
                     ${OPENSSL_TEST_DIR}/session.pem)
    return()
  endif ()

  if ("${name}" STREQUAL cmp_ctx_test)
    add_openssl_test(OPENSSL3 "${name}" "${name}"
                     ${OPENSSL_TEST_DIR}/certs/ee-cert.pem)
    return()
  endif ()

  if ("${name}" STREQUAL cmp_msg_test)
    add_openssl_test(
      OPENSSL3
      "${name}"
      "${name}"
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_msg_data/new.key
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_msg_data/server.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_msg_data/pkcs10.der
      "default"
      ${OPENSSL_TEST_DIR}/default.cnf)
    return()
  endif ()

  if ("${name}" STREQUAL cmp_protect_test)
    add_openssl_test(
      OPENSSL3
      "${name}"
      "${name}"
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_protect_data/server.pem
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_protect_data/IR_protected.der
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_protect_data/IR_unprotected.der
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_protect_data/IP_PBM.der
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_protect_data/server.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_protect_data/server.pem
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_protect_data/EndEntity1.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_protect_data/EndEntity2.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_protect_data/Root_CA.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_protect_data/Intermediate_CA.crt
      "default"
      ${OPENSSL_TEST_DIR}/default.cnf)
    return()
  endif ()

  if ("${name}" STREQUAL cmp_server_test)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}"
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_server_data/CR_protected_PBM_1234.der
      "default" ${OPENSSL_TEST_DIR}/default.cnf)
    return()
  endif ()

  if ("${name}" STREQUAL cmp_vfy_test)
    add_openssl_test(
      OPENSSL3
      "${name}"
      "${name}"
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/server.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/client.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/EndEntity1.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/EndEntity2.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/Root_CA.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/Intermediate_CA.crt
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/IR_protected.der
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/IR_unprotected.der
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/IP_waitingStatus_PBM.der
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/IR_rmprotection.der
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/insta.cert.pem
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/insta_ca.cert.pem
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/IR_protected_0_extraCerts.der
      ${OPENSSL_RECIPE_DIR}/65-test_cmp_vfy_data/IR_protected_2_extraCerts.der
      "default"
      ${OPENSSL_TEST_DIR}/default.cnf)
    return()
  endif ()

  if ("${name}" STREQUAL cmsapitest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_TEST_DIR}/certs/servercert.pem
      ${OPENSSL_TEST_DIR}/certs/serverkey.pem)
    return()
  endif ()

  if ("${name}" STREQUAL confdump)
    add_openssl_test(
      OPENSSL3 "${name}-dollarid_on" "${name}"
      ${OPENSSL_RECIPE_DIR}/04-test_conf_data/dollarid_on.cnf
      ${OPENSSL_RECIPE_DIR}/04-test_conf_data/dollarid_on.txt)
    add_openssl_test(
      OPENSSL3 "${name}-dollarid_off" "${name}"
      ${OPENSSL_RECIPE_DIR}/04-test_conf_data/dollarid_off.cnf
      ${OPENSSL_RECIPE_DIR}/04-test_conf_data/dollarid_off.txt)
    return()
  endif ()

  if ("${name}" STREQUAL conf_include_test)
    # This test fails with DEBUG_MALLOC because of the use of setenv.
    if (NOT USE_DEBUG_MALLOC)
      add_openssl_test(OPENSSL3 "${name}-includes" "${name}"
                       ${OPENSSL_RECIPE_DIR}/90-test_includes_data/includes.cnf)
      add_openssl_test(
        OPENSSL3 "${name}-includes-file" "${name}"
        ${OPENSSL_RECIPE_DIR}/90-test_includes_data/includes-file.cnf)
      add_openssl_test(
        OPENSSL3 "${name}-includes-eq" "${name}"
        ${OPENSSL_RECIPE_DIR}/90-test_includes_data/includes-eq.cnf)
      add_openssl_test(
        OPENSSL3 "${name}-includes-eq-ws" "${name}"
        ${OPENSSL_RECIPE_DIR}/90-test_includes_data/includes-eq-ws.cnf)
      if (OPENSSL3)
        add_openssl_test(
          OPENSSL3 "${name}-includes-broken" "${name}" "-f"
          ${OPENSSL_RECIPE_DIR}/90-test_includes_data/includes-broken.cnf)
      else ()
        add_openssl_test(
          OPENSSL3 "${name}-includes-broken" "${name}"
          ${OPENSSL_RECIPE_DIR}/90-test_includes_data/includes-broken.cnf "f")
      endif ()
    endif ()
    return()
  endif ()

  if ("${name}" STREQUAL ct_test)
    add_openssl_test(OPENSSL3 "${name}" "${name}")
    add_openssl_tests_properties(
      OPENSSL3
      ${name}
      PROPERTIES
      ENVIRONMENT
      "CTLOG_FILE=${OPENSSL_CTLOG_FILE};CT_DIR=${TEST_DATA_DIR}/ct;CERTS_DIR=${TEST_DATA_DIR}/certs"
    )
    return()
  endif ()

  if ("${name}" STREQUAL d2i_test)
    add_openssl_test(OPENSSL3 "${name}-bad_cert" "${name}" "X509" "decode"
                     ${OPENSSL_TEST_DIR}/d2i-tests/bad_cert.der)
    add_openssl_test(
      OPENSSL3 "${name}-bad_generalname" "${name}" "GENERAL_NAME" "decode"
      ${OPENSSL_TEST_DIR}/d2i-tests/bad_generalname.der)
    add_openssl_test(OPENSSL3 "${name}-bad_bio" "${name}" "ASN1_ANY" "BIO"
                     ${OPENSSL_TEST_DIR}/d2i-tests/bad_bio.der)
    add_openssl_test(OPENSSL3 "${name}-high_tag" "${name}" "ASN1_ANY" "OK"
                     ${OPENSSL_TEST_DIR}/d2i-tests/high_tag.der)
    add_openssl_test(
      OPENSSL3 "${name}-high_tag_integer" "${name}" "ASN1_INTEGER" "decode"
      ${OPENSSL_TEST_DIR}/d2i-tests/high_tag.der)
    add_openssl_test(OPENSSL3 "${name}-int0" "${name}" "ASN1_INTEGER" "OK"
                     ${OPENSSL_TEST_DIR}/d2i-tests/int0.der)
    add_openssl_test(OPENSSL3 "${name}-int1" "${name}" "ASN1_INTEGER" "OK"
                     ${OPENSSL_TEST_DIR}/d2i-tests/int1.der)
    add_openssl_test(OPENSSL3 "${name}-intminus1" "${name}" "ASN1_INTEGER" "OK"
                     ${OPENSSL_TEST_DIR}/d2i-tests/intminus1.der)
    add_openssl_test(OPENSSL3 "${name}-int0-any" "${name}" "ASN1_ANY" "OK"
                     ${OPENSSL_TEST_DIR}/d2i-tests/int0.der)
    add_openssl_test(OPENSSL3 "${name}-int1-any" "${name}" "ASN1_ANY" "OK"
                     ${OPENSSL_TEST_DIR}/d2i-tests/int1.der)
    add_openssl_test(OPENSSL3 "${name}-intminus1-any" "${name}" "ASN1_ANY" "OK"
                     ${OPENSSL_TEST_DIR}/d2i-tests/intminus1.der)
    add_openssl_test(OPENSSL3 "${name}-bad-int-pad0" "${name}" "ASN1_INTEGER"
                     "decode" ${OPENSSL_TEST_DIR}/d2i-tests/bad-int-pad0.der)
    add_openssl_test(
      OPENSSL3 "${name}-bad-int-padminus1" "${name}" "ASN1_INTEGER" "decode"
      ${OPENSSL_TEST_DIR}/d2i-tests/bad-int-padminus1.der)
    return()
  endif ()

  if ("${name}" STREQUAL danetest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" "example.com"
      ${OPENSSL_TEST_DIR}/danetest.pem ${OPENSSL_TEST_DIR}/danetest.in)
    return()
  endif ()

  if ("${name}" STREQUAL dtlstest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_APPS_DIR}/server.pem
      ${OPENSSL_APPS_DIR}/server.pem)
    return()
  endif ()

  if ("${name}" STREQUAL ec_internal_test)
    # Disable for code coverage
    # As this test would write code coverage data to incorrect directory
    if (CODE_COVERAGE)
      return()
    endif ()

    if (WIN32)
      add_openssl_test(OPENSSL3 "${name}" "${name}" ${TEST_DATA_DIR} ${WIN32})
    else ()
      add_openssl_test(OPENSSL3 "${name}" "${name}" ${TEST_DATA_DIR})
    endif ()
    return()
  endif ()

  if ("${name}" STREQUAL ectest)
    add_openssl_test(OPENSSL3 "${name}" "${name}")
    return()
  endif ()

  if ("${name}" STREQUAL endecoder_legacy_test)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_TEST_DIR}/certs/ee-key.pem
      ${OPENSSL_TEST_DIR}/certs/dhk2048.pem)
    return()
  endif ()

  if ("${name}" STREQUAL enginetest)
    add_openssl_test(OPENSSL3 "${name}" "${name}"
                     ${OPENSSL_TEST_DIR}/certs/root-cert.pem)
    return()
  endif ()

  if ("${name}" STREQUAL evp_test)
    if (OPENSSL3)
      set(EVP_TEST_LIST ${OPENSSL_3_EVP_TEST_LIST})
      set(EVP_TEST_DATA_DIR ${TEST_DATA_DIR}/30-test_evp_data/openssl_3)
    else ()
      set(EVP_TEST_LIST ${OPENSSL_1_EVP_TEST_LIST})
      set(EVP_TEST_DATA_DIR ${TEST_DATA_DIR}/30-test_evp_data/openssl)
    endif ()
    foreach (subtestname ${EVP_TEST_LIST})
      add_openssl_test(OPENSSL3 "${name}-${subtestname}" "${name}"
                       ${EVP_TEST_DATA_DIR}/${subtestname}.txt)
    endforeach ()
    return()
  endif ()

  if ("${name}" STREQUAL evp_fetch_prov_test)
    add_openssl_test(OPENSSL3 "${name}" "${name}")
    add_openssl_tests_properties(OPENSSL3 "${name}" PROPERTIES ENVIRONMENT
                                 OPENSSL_CONF=${OPENSSL_APPS_DIR}/openssl.cnf)

    return()
  endif ()

  if ("${name}" STREQUAL evp_pkey_provided_test)
    add_openssl_test(OPENSSL3 "${name}" "${name}"
                     ${OPENSSL_RECIPE_DIR}/30-test_evp_pkey_provided)
    return()
  endif ()

  if ("${name}" STREQUAL fatalerrtest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_APPS_DIR}/server.pem
      ${OPENSSL_APPS_DIR}/server.pem)
    return()
  endif ()

  if ("${name}" STREQUAL keymgmt_internal_test)
    add_openssl_test(OPENSSL3 "${name}" "${name}"
                     ${OPENSSL_TEST_DIR}/certs/ee-cert.pem)
    return()
  endif ()

  if ("${name}" STREQUAL memleaktest)
    add_openssl_test(OPENSSL3 "${name}" "${name}" "freeit")
    return()
  endif ()

  if ("${name}" STREQUAL ocspapitest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}"
      ${OPENSSL_RECIPE_DIR}/80-test_ocsp_data/cert.pem
      ${OPENSSL_RECIPE_DIR}/80-test_ocsp_data/key.pem)
    return()
  endif ()

  if ("${name}" STREQUAL ossl_store_test)
    add_openssl_test(
      OPENSSL3
      "${name}"
      "${name}"
      "-dir"
      ${OPENSSL_TEST_DIR}
      "-in"
      "testrsa.pem"
      "-sm2"
      "certs/sm2-root.crt"
      "-data"
      ${OPENSSL_RECIPE_DIR}/66-test_ossl_store_data)
    return()
  endif ()

  if ("${name}" STREQUAL params_conversion_test)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}"
      ${TEST_DATA_DIR}/04-test_params_conversion_data/native_types.txt)
    return()
  endif ()

  if ("${name}" STREQUAL pemtest)
    add_openssl_test(OPENSSL3 "${name}" "${name}"
                     ${OPENSSL_APPS_DIR}/server.pem)
    return()
  endif ()

  if ("${name}" STREQUAL pem_read_depr_test)
    add_openssl_test(OPENSSL3 "${name}" "${name}"
                     ${OPENSSL_RECIPE_DIR}/04-test_pem_read_depr_data)
    return()
  endif ()

  if ("${name}" STREQUAL provider_internal_test)
    add_openssl_test(OPENSSL3 "${name}" "${name}")
    add_openssl_tests_properties(
      OPENSSL3 "${name}" PROPERTIES ENVIRONMENT
      OPENSSL_CONF=${OPENSSL_TEST_DIR}/provider_internal_test.cnf)
    return()
  endif ()

  if ("${name}" STREQUAL provider_status_test)
    add_openssl_test(OPENSSL3 "${name}" "${name}" "-provider_name" "default")
    return()
  endif ()

  if ("${name}" STREQUAL recordlentest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_APPS_DIR}/server.pem
      ${OPENSSL_APPS_DIR}/server.pem)
    return()
  endif ()

  if ("${name}" STREQUAL servername_test)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_APPS_DIR}/server.pem
      ${OPENSSL_APPS_DIR}/server.pem)
    return()
  endif ()

  if ("${name}" STREQUAL shlibloadtest)
    add_openssl_test(
      OPENSSL3
      "${name}-cryptofirst"
      "${name}"
      "-crypto_first"
      "libcrypto"
      "libssl"
      "atexit-cryptofirst.txt")
    add_openssl_test(
      OPENSSL3
      "${name}-sslfirst"
      "${name}"
      "-ssl_first"
      "libcrypto"
      "libssl"
      "atexit-sslfirst.txt")
    add_openssl_test(
      OPENSSL3
      "${name}-justcrypto"
      "${name}"
      "-just_crypto"
      "libcrypto"
      "libssl"
      "atexit-libssl.txt")
    add_openssl_test(
      OPENSSL3
      "${name}-dsoref"
      "${name}"
      "-dso_ref"
      "libcrypto"
      "libssl"
      "atexit-dsoref.txt")
    add_openssl_test(
      OPENSSL3
      "${name}-noatexit"
      "${name}"
      "-no_atexit"
      "libcrypto"
      "libssl"
      "atexit-noatexit.txt")
    return()
  endif ()

  if ("${name}" STREQUAL ssl_test)
    if (OPENSSL3)
      set(SSL_TEST_LIST
          01-simple
          02-protocol-version
          03-custom_verify
          04-client_auth
          05-sni
          06-sni-ticket
          07-dtls-protocol-version
          08-npn
          09-alpn
          10-resumption
          11-dtls_resumption
          #12-ct                      # NOTE: requires ct
          13-fragmentation
          14-curves
          15-certstatus
          16-dtls-certstatus
          17-renegotiate
          18-dtls-renegotiate
          19-mac-then-encrypt
          20-cert-select
          21-key-update
          #22-compression             # NOTE: requires zlib
          #23-srp                     # NOTE: requires srp
          24-padding
          #25-cipher                  # NOTE: requires chacha and poly1305
          26-tls13_client_auth
          27-ticket-appdata
          28-seclevel
          #29-dtls-sctp-label-bug     # NOTE: requires sctp
          30-extended-master-secret)
    else ()
      set(SSL_TEST_LIST
          01-simple
          02-protocol-version
          04-client_auth
          05-sni
          07-dtls-protocol-version
          10-resumption
          11-dtls_resumption
          16-dtls-certstatus
          17-renegotiate
          18-dtls-renegotiate
          19-mac-then-encrypt
          20-cert-select
          27-ticket-appdata
          28-seclevel)
    endif ()
    foreach (cnffilename ${SSL_TEST_LIST})
      set(subtest_name "${name}-${cnffilename}")
      if (OPENSSL3)
        add_openssl_test(
          OPENSSL3 "${subtest_name}" "${name}"
          "${OPENSSL_TEST_DIR}/ssl-tests/${cnffilename}.cnf" "default"
          ${OPENSSL_TEST_DIR}/default.cnf)
      else ()
        add_openssl_test(OPENSSL3 "${subtest_name}" "${name}"
                         "${OPENSSL_TEST_DIR}/ssl-tests/${cnffilename}.conf")
      endif ()
      add_openssl_tests_properties(
        OPENSSL3
        ${subtest_name}
        PROPERTIES
        ENVIRONMENT
        "CTLOG_FILE=${OPENSSL_CTLOG_FILE};TEST_CERTS_DIR=${OPENSSL_TEST_DIR}/certs"
      )
    endforeach ()
    return()
  endif ()

  if ("${name}" STREQUAL ssl_test_ctx_test)
    if (OPENSSL3)
      add_openssl_test(OPENSSL3 "${name}" "${name}"
                       ${OPENSSL_TEST_DIR}/ssl_test_ctx_test.cnf)
    else ()
      add_openssl_test(OPENSSL3 "${name}" "${name}"
                       ${OPENSSL_TEST_DIR}/ssl_test_ctx_test.conf)
    endif ()
    return()
  endif ()

  if ("${name}" STREQUAL sslapitest)
    add_openssl_test(
      OPENSSL3
      "${name}"
      "${name}"
      ${OPENSSL_TEST_DIR}/certs
      ${OPENSSL_RECIPE_DIR}/90-test_sslapi_data/passwd.txt
      ${TEST_DATA_DIR}/tmpfile
      "default"
      ${OPENSSL_TEST_DIR}/default.cnf
      ${OPENSSL_RECIPE_DIR}/90-test_sslapi_data/dhparams.pem)
    return()
  endif ()

  if ("${name}" STREQUAL sslbuffertest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_APPS_DIR}/server.pem
      ${OPENSSL_APPS_DIR}/server.pem)
    return()
  endif ()

  if ("${name}" STREQUAL sslcorrupttest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_APPS_DIR}/server.pem
      ${OPENSSL_APPS_DIR}/server.pem)
    return()
  endif ()

  if ("${name}" STREQUAL sysdefaulttest)
    add_openssl_test(OPENSSL3 "${name}" "${name}")
    add_openssl_tests_properties(
      OPENSSL3 "${name}" PROPERTIES ENVIRONMENT
      OPENSSL_CONF=${OPENSSL_TEST_DIR}/sysdefault.cnf)
    return()
  endif ()

  if ("${name}" STREQUAL threadstest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" "-config" "${OPENSSL_TEST_DIR}/default.cnf"
      ${OPENSSL_RECIPE_DIR}/90-test_threads_data)
    return()
  endif ()

  if ("${name}" STREQUAL tls13ccstest)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_APPS_DIR}/server.pem
      ${OPENSSL_APPS_DIR}/server.pem)
    return()
  endif ()

  if ("${name}" STREQUAL v3ext)
    add_openssl_test(OPENSSL3 "${name}" "${name}"
                     ${OPENSSL_TEST_DIR}/certs/pathlen.pem)
    return()
  endif ()

  if ("${name}" STREQUAL verify_extra_test)
    add_openssl_test(OPENSSL3 "${name}" "${name}" ${OPENSSL_TEST_DIR}/certs/)
    return()
  endif ()

  if ("${name}" STREQUAL x509_check_cert_pkey_test)
    add_openssl_test(
      OPENSSL3
      "${name}-rsa-cert"
      "${name}"
      ${OPENSSL_TEST_DIR}/certs/servercert.pem
      ${OPENSSL_TEST_DIR}/certs/serverkey.pem
      "cert"
      "ok")
    add_openssl_test(
      OPENSSL3
      "${name}-mismatched-rsa-cert"
      "${name}"
      ${OPENSSL_TEST_DIR}/certs/servercert.pem
      ${OPENSSL_TEST_DIR}/certs/wrongkey.pem
      "cert"
      "failed")
    add_openssl_test(
      OPENSSL3
      "${name}-dsa-cert"
      "${name}"
      ${OPENSSL_TEST_DIR}/certs/server-dsa-cert.pem
      ${OPENSSL_TEST_DIR}/certs/server-dsa-key.pem
      "cert"
      "ok")
    add_openssl_test(
      OPENSSL3
      "${name}-ec-cert"
      "${name}"
      ${OPENSSL_TEST_DIR}/certs/server-ecdsa-cert.pem
      ${OPENSSL_TEST_DIR}/certs/server-ecdsa-key.pem
      "cert"
      "ok")
    add_openssl_test(
      OPENSSL3
      "${name}-rsa-req"
      "${name}"
      ${OPENSSL_TEST_DIR}/certs/x509-check.csr
      ${OPENSSL_TEST_DIR}/certs/x509-check-key.pem
      "req"
      "ok")
    add_openssl_test(
      OPENSSL3
      "${name}-mismatched-rsa-req"
      "${name}"
      ${OPENSSL_TEST_DIR}/certs/x509-check.csr
      ${OPENSSL_TEST_DIR}/certs/wrongkey.pem
      "req"
      "failed")
    return()
  endif ()

  if ("${name}" STREQUAL x509_dup_cert_test)
    add_openssl_test(
      OPENSSL3 "${name}" "${name}" ${OPENSSL_TEST_DIR}/certs/roots.pem
      ${OPENSSL_TEST_DIR}/certs/leaf.pem)
    return()
  endif ()

  if ("${name}" STREQUAL x509aux)
    add_openssl_test(
      OPENSSL3
      "${name}"
      "${name}"
      ${OPENSSL_TEST_DIR}/certs/roots.pem
      ${OPENSSL_TEST_DIR}/certs/root+anyEKU.pem
      ${OPENSSL_TEST_DIR}/certs/root-anyEKU.pem
      ${OPENSSL_TEST_DIR}/certs/root-cert.pem
      ${OPENSSL_TEST_DIR}/certs/invalid-cert.pem)
    return()
  endif ()

  # If the test isn't one of the above cases, it doesn't need arguments.
  add_openssl_test(OPENSSL3 "${name}" "${name}")
endfunction (add_openssl_test_supported)

# Add all tests for OpenSSL 1.1
file(STRINGS "tests.supported" openssltests)
foreach (testcase ${openssltests})
  get_testcase_name(${testcase} name "../../3rdparty/openssl/openssl/test/")
  add_openssl_test_supported(name FALSE)
endforeach (testcase)

# Add all tests for OpenSSL 3.0
file(STRINGS "tests_3.supported" openssltests_3)
foreach (testcase ${openssltests_3})
  get_testcase_name(${testcase} name "../../3rdparty/openssl/openssl_3/test/")
  add_openssl_test_supported(name TRUE)
endforeach (testcase)
